package com.gintama;

import org.junit.jupiter.api.Test;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

public class ThreadDemo {

    /**
     * @author wcc
     * @date 2021/8/21 20:46
     * 现在有T1、T2、T3三个线程，你怎样保证T2在T1执行完后执行，T3在T2执行完后执行？
     */
    @Test
    public void joinDemo(){
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("t1 is running");
            }
        });
        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("t2 is running");
            }
        });
        Thread t3 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("t3 is running");
            }
        });
        t1.start();
        t2.start();
        t3.start();
    }

    @Test
    public void ticketDemo(){
        SellTicket st = new SellTicket();

        Thread t1 = new Thread(st, "窗口1");
        Thread t2 = new Thread(st, "窗口2");
        Thread t3 = new Thread(st, "窗口3");

        t1.start();
        t2.start();
        t3.start();
    }

    /*
	创建线程的方式三: 实现callable接口 ---JDK 5.0 新增
	1.创建一个实现Callable接口的实现类
	2.实现call方法,将此线程需要执行的操作声明在call()中
	3.创建callable接口实现类的对象
	4.将此callable的对象作为参数传入到FutureTask构造器中,创建FutureTask的对象
	5.将FutureTask对象作为参数传递到Thread类的构造器中,创建Thread对象,并调用star
	6.获取callable接口中call方法的返回值
	* */
    @Test
    public void callDemo() throws ExecutionException, InterruptedException {
        //实现Callable接口 + FutureTask （可以拿到返回结果，可以处理异常）
        FutureTask<Integer> futureTask = new FutureTask<>(new CallableDemo());
        new Thread(futureTask).start();
        //阻塞等待整个线程执行完成，获取返回结果
        Integer integer = futureTask.get();
        System.out.println(integer);
    }

    /**
     * 1. get( )方法建议放在最后一行,防止线程阻塞(一旦调用了get( )方法,不管是否计算完成都会阻塞)
     * 2. 一个FutureTask,多个线程调用call( )方法只会调用一次
     * 3. 如果需要调用call方法多次,则需要多个FutureTask
     */
    @Test
    public void callDemo1() throws Exception{
        FutureTask<Integer> futureTask = new FutureTask<>(new CallableDemo());
        new Thread(futureTask,"thread1").start();
        new Thread(futureTask,"thread2").start();
        Integer integer = futureTask.get();
        System.out.println(integer);


    }

    @Test
    public void callDemo2() throws Exception{
        Ticket ticket = new Ticket();
        new Thread(() -> { for (int i = 0; i <35; i++)  ticket.sale(); },"a").start();
        new Thread(() -> { for (int i = 0; i <35; i++)  ticket.sale(); },"b").start();
        new Thread(() -> { for (int i = 0; i <35; i++)  ticket.sale(); },"c").start();


    }

}
